import { EventFormatter } from '../utils';
import { Channel } from './channel';

/**
 * This class represents a Socket.io channel.
 */
export class WeappSocketChannel extends Channel {
    /**
     * The Socket.io client instance.
     */
    socket;

    /**
     * The name of the channel.
     */
    name;

    /**
     * Channel options.
     */
    options;

    /**
     * The event formatter.
     */
    eventFormatter;

    /**
     * The event callbacks applied to the channel.
     */
    events = {};

    /**
     * Create a new class instance.
     */
    constructor(socket, name, options) {
        super();		
        this.name = name;
        this.socket = socket;
        this.options = options;
        this.eventFormatter = new EventFormatter(this.options.namespace);
		console.log('频道：',name);
		this.subscribe();
		this.configureReconnector();
        
    }

    /**
     * Subscribe to a Socket.io channel.
     */
    subscribe() {
        this.socket.emit('subscribe', {
            channel: this.name,
            auth: this.options.auth || {}
        });
    }

    /**
     * Unsubscribe from channel and ubind event callbacks.
     */
    unsubscribe() {
        this.unbind();

        this.socket.emit('unsubscribe', {
            channel: this.name,
            auth: this.options.auth || {}
        });
    }

    /**
     * Listen for an event on the channel instance.
     */
    listen(event, callback) {
		console.log('事件：',this.eventFormatter.format(event));
        this.on(this.eventFormatter.format(event), callback);

        return this;
    }

    /**
     * Stop listening for an event on the channel instance.
     */
    stopListening(event) {
        const name = this.eventFormatter.format(event);
        this.socket.removeListener(name);
        delete this.events[name];

        return this;
    }

    /**
     * Bind the channel's socket to an event and store the callback.
     */
    on(event, callback) {
        let listener = (channel, data) => {
            if (this.name == channel) {
                callback(data);
            }
        };

        this.socket.on(event, listener);
        this.bind(event, listener);
    }

    /**
     * Attach a 'reconnect' listener and bind the event.
     */
    configureReconnector() {
        const listener = () => {
            this.subscribe();
        };

        this.socket.on('reconnect', listener);
        this.bind('reconnect', listener);
    }

    /**
     * Bind the channel's socket to an event and store the callback.
     */
    bind(event, callback) {
        this.events[event] = this.events[event] || [];
        this.events[event].push(callback);
    }

    /**
     * Unbind the channel's socket from all stored event callbacks.
     */
    unbind() {
        Object.keys(this.events).forEach(event => {
            this.events[event].forEach(callback => {
                this.socket.removeListener(event, callback);
            });

            delete this.events[event];
        });
    }
}
